from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.orm.session import Session

from airflow.models.idata_auth_role import AuthRole
from airflow.models.base import Base
from airflow.models.idata_project_user import ProjectUser
from airflow.utils.session import provide_session

association_table = Table('idata_auth_user_role', Base.metadata,
                          Column('role_id', Integer, ForeignKey('idata_auth_role.id')),
                          Column('oa_user_name', String(32), ForeignKey('idata_user.oa_user_name'))
                          )


class User(Base):
    """the class to get user info."""

    __tablename__ = "idata_user"
    __table_args__ = {"useexisting": True}

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_name = Column(String(32), nullable=False)
    oa_user_name = Column(String(32), nullable=False)
    department_name = Column(String(64), nullable=False)
    create_by = Column(String(32), nullable=False)
    create_time = Column(DateTime, nullable=False)
    enable = Column(Integer, nullable=False)
    roles = relationship("AuthRole", secondary=association_table)

    def __init__(self, user_name, oa_user_name, department_name, create_by, create_time):
        self.user_name = user_name
        self.oa_user_name = oa_user_name
        self.department_name = department_name
        self.create_by = create_by
        self.create_time = create_time
        self.enable = 0

    @staticmethod # 静态方法
    @provide_session
    def get_user(id, session: Session = None):
        """
        Get the user with specific oa_user_name.

        :param oa_user_name: The task id of the Task to get.
        :param session: SQLAlchemy ORM Session
        :return: the User object
        """
        return session.query(User).filter(User.id == id).first()

    @staticmethod #静态方法
    @provide_session
    def get_user_by_oausername(oa_user_name, session: Session = None):
        """
        Get the user with specific oa_user_name.

        :param oa_user_name: The task id of the Task to get.
        :param session: SQLAlchemy ORM Session
        :return: the User object
        """
        return session.query(User).filter(User.oa_user_name == oa_user_name).first()

    @staticmethod #静态方法
    @provide_session
    def get_users(session: Session = None):
        """
        Get the user with specific oa_user_name.

        :param oa_user_name: The task id of the Task to get.
        :param session: SQLAlchemy ORM Session
        :return: the User object
        """
        return session.query(User).all()

    @staticmethod #静态方法
    @provide_session
    def get_users_page(page , session: Session = None):
        """
        Get the user with specific oa_user_name.

        :param oa_user_name: The task id of the Task to get.
        :param session: SQLAlchemy ORM Session
        :return: the User object
        """
        return session.query(User).order_by(User.create_time).paginate(page,10,error_out=False)

    @staticmethod #静态方法
    @provide_session
    def add_user(user , session: Session = None):
        """
        Get the user with specific oa_user_name.

        :param oa_user_name: The task id of the Task to get.
        :param session: SQLAlchemy ORM Session
        :return: the User object
        """
        return session.add(user)

    @staticmethod #静态方法
    @provide_session
    def delete_user(id , session: Session = None):
        """
        delte the user by id.

        :param id: The task id of the Task to get.
        """
        session.query(User).filter(User.id == id).delete()

    @staticmethod #静态方法
    @provide_session
    def update_user(user , session: Session = None):
        result = session.query(User).filter(User.id == user.id).first()
        if result is None:
            return
        else:
            return session.merge(user)

    @staticmethod #静态方法
    @provide_session
    def get_project_users(id , page , session: Session = None):
        return session.query(User).outerjoin(ProjectUser,User.oa_user_name == ProjectUser.oa_user_name) \
            .filter(ProjectUser.project_id == id).paginate(page,10,error_out=False)

    def to_json(self):
        """
        Get the User in a json structure
        :return: the User object in json format
        """
        if self is None:
            return None
        data = {
            'id': self.id,
            'user_name': self.user_name,
            'oa_user_name': self.oa_user_name,
            'department_name': self.department_name,
            'create_by': self.create_by,
            'create_time': self.create_time,
            'roles':  list(map(AuthRole.to_json,self.roles)),
            'enable': self.enable
        }
        return data


# class BaseQuery(User,session = None):




